import axios from 'axios'
// 引入 axios自带的 请求接口request参数类型 以及 请求接口headers头参数类型
import type { AxiosError, AxiosRequestConfig, AxiosRequestHeaders } from 'axios'
import { ElMessage } from 'element-plus'
// import { useUserStore } from '@/stores/modules/user'
import myConfig from '@/apis/config'

// 1、自定义请求接口headers头参数类型
type RequestHeader = AxiosRequestHeaders & { SourceClient?: string }

// 2、自定义请求接口request参数类型，可以加一些自己自定义的参数
interface RequestConfig extends AxiosRequestConfig {
  headers?: RequestHeader // 放入请求头
  noNeedToken?: boolean // 该接口是否需要token
  mock?: boolean // 是否开启mock
}

interface RequestInterceptorsConfig extends RequestConfig {
  // 请求拦截器使用
  headers: RequestHeader
}

const baseURL = '' //import.meta.env.VITE_APP_BASE_API, // /api  vite.config.ts 配置代理服务器后不需要
/* 创建请求实例 */
const service = axios.create({
  // timeout: 10000
})
/* 添加请求拦截器 */
service.interceptors.request.use(
  (config: RequestInterceptorsConfig) => {
    // 对请求参数进行处理 默认get
    config.method = config.method || 'get'

    // 统一都传data 这里根据方式判断改成对应的
    if (config.method.toLowerCase() === 'get') {
      config.params = config.data
    }

    // 对请求data中mock可覆盖config.mock 开关处理
    let isMock = myConfig.mock
    if (typeof config.mock !== 'undefined') {
      isMock = config.mock
      delete config.mock
    }

    // 拼接请求地址
    config.url = isMock ? myConfig.mockUrl + config.url : myConfig.baseUrl + config.url
    // 1. 非 http 开头需拼接地址
    if (!config.url?.startsWith('http')) {
      config.url = baseURL + config.url
    }
    // 2. 请求超时
    config.timeout = 10000
    // 3. 添加小程序端请求头标识miniapp 网页端标识web
    config.headers.SourceClient = 'web'
    // 4. 添加 token 请求头标识
    if (config.noNeedToken) {
      // 自定义的参数，是否不需要token的接口
      return config
    }
    // 4. 添加 token 请求头标识
    // const memberStore = useUserStore()
    // const token = memberStore.token
    // if (token) {
    //   config.headers.Authorization = token
    // }
    return config
  },
  (error: AxiosError) => {
    // 请求错误拦截
    return Promise.reject(error)
  }
)

// 传入泛型约束返回数据类型
// ApiResponse 主体后端返回格式
type IResult<T> = {
  code: number
  ok?: boolean
  message?: string
  data: T // 这里定义请求返回data数据类型
}

/* 封装实例的请求方法 */
const request = async <T>(config: RequestConfig) => {
  // 1. 返回 Promise 对象
  return new Promise<IResult<T>>((resolve, reject) => {
    service
      .request(config)
      // 服务器有响应
      .then((res) => {
        // 状态码 2xx，参考 axios 的设计
        if (res.status >= 200 && res.status < 300) {
          // 判断返回数据部分状态
          if (res.data.code === 200) {
            // 2.1 提取核心数据 res.data
            resolve(res.data as IResult<T>)
          } else if (res.data.code === 401) {
            // 401错误  -> 清理用户信息，跳转到登录页
            // const memberStore = useUserStore()
            // memberStore.userLogout()
            // 带上原页面地址 跳转登录页
            ElMessage({ type: 'error', message: res.data.data?.message })
            reject(res)
          } else {
            ElMessage({ type: 'error', message: res.data.data?.message || '后端无返回' })
            reject(res)
          }
        } else {
          // 其他错误 -> 根据后端错误信息轻提示'请求错误'
          ElMessage({ type: 'error', message: res.data.data?.message || '后端无返回' })
          reject(res)
        }
      })
      // 服务器没有响应
      .catch((err) => {
        let message = ''
        const status = err.response?.status
        // 提示  500服务器没有返回或404请求地址错误没有返回，网络或服务器错误没有返回信息，换个网络试试'
        // console.log('catch', err.response.status, err.message)
        switch (status) {
          case 401:
            message = '身份认证错误！'
            break
          case 403:
            message = '无权访问！'
            break
          case 404:
            message = '请求地址错误！'
            break
          case 500:
            message = '服务器故障！'
            break
          default:
            message = '网络故障！'
            break
        }
        ElMessage({ type: 'error', message })
        reject(err)
      })
  })
}

export default request
